#include <iostream>

using std::cout;
using std::endl;

class Base
{
public:
    Base(long base = 0)
    : _base(base)
    {
        cout << "Base(long  = 0)" << endl;
    }

    ~Base()
    {
        cout << "~Base()" <<  endl;
    }

    virtual
    void func()
    {
        cout << "virtual void Base::func()" << endl;
    }

    virtual
    void gunc()
    {
        cout << "virtual void Base::gunc()" << endl;
    }

    virtual
    void hunc()
    {
        cout << "virtual void Base::hunc()" << endl;
    }
private:
    long _base;
};

class Derived
: public Base
{
public:
    Derived(long base = 0, long derived = 0)
    : Base(base)
    , _derived(derived)
    {
        cout << "Derived(long  = 0, long = 0)" << endl;
    }

    ~Derived()
    {
        cout << "~Derived()" <<  endl;
    }

    virtual
    void func()
    {
        cout << "virtual void Derived::func()" << endl;
    }

    virtual
    void gunc()
    {
        cout << "virtual void Derived::gunc()" << endl;
    }

    virtual
    void hunc()
    {
        cout << "virtual void Derived::hunc()" << endl;
    }
private:
    long _derived;
};

void test()
{
    //虚表是存在的,位于只读段，普通的单继承而言虚表就是唯一的
    cout <<"sizeof(Derived) = " << sizeof(Derived) << endl;
    cout <<endl;
    Derived d(10, 20);//栈对象
    printf("打印对象d的地址 : %p\n", &d);
    printf("打印对象d的地址 : %p\n", (long *)&d);
    printf("打印虚表的地址 : %p\n", (long *)*(long *)&d);
    printf("第一个虚函数的入口地址: %p\n", 
           (long *)*(long *)*(long *)&d);

    cout << endl;
    Derived d2(100, 200);//栈对象
    printf("打印对象d2的地址 : %p\n", &d2);
    printf("打印对象d2的地址 : %p\n", (long *)&d2);
    printf("打印虚表的地址 : %p\n", (long *)*(long *)&d2);
    printf("第一个虚函数的入口地址: %p\n", 
           (long *)*(long *)*(long *)&d2);

    cout << endl;


    typedef void (*pFunc)();
    /* typedef void (*)() pFunc;//语法上不支持,error */
    /* typedef int A;//ok */
    /* void (*pFunc)(); */
    pFunc f = (pFunc)*((long *)*(long *)&d);
    printf("打印第一个虚函数的地址: %p\n", f);
    f();//执行了第一个虚函数

    cout << endl;
    pFunc f2 = (pFunc)*((long *)*(long *)&d + 1);
    printf("打印第二个虚函数的地址: %p\n", f2);
    f2();//执行了第二个虚函数

    cout << endl;
    pFunc f3 = (pFunc)*((long *)*(long *)&d + 2);
    printf("打印第三个虚函数的地址: %p\n", f3);
    f3();//执行了第三个虚函数


    cout << endl << endl;
    cout << "_base = " << (long )*((long *)&d + 1) << endl;
    cout << "_derived = " << (long )*((long *)&d + 2) << endl;

}

int main(int argc, char *argv[])
{
    test();
    return 0;
}

